package com.xinchuang.service.image.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.lang.generator.SnowflakeGenerator;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.common.collect.Lists;
import com.xinchuang.comment.KeyWord;
import com.xinchuang.comment.R;
import com.xinchuang.common.KeyWordSystem;
import com.xinchuang.constant.ImageTypeConstant;
import com.xinchuang.entity.common.ImgTargetTable;
import com.xinchuang.entity.image.ImageCut;
import com.xinchuang.entity.image.ImageEditing;
import com.xinchuang.entity.image.TaskRun;
import com.xinchuang.enums.CutEnum;
import com.xinchuang.enums.ImageCutEnum;
import com.xinchuang.enums.ImageEditingEnum;
import com.xinchuang.mapper.image.TaskRunMapper;
import com.xinchuang.service.common.ImgTargetTableService;
import com.xinchuang.service.image.GDALService;
import com.xinchuang.service.image.ImageCutService;
import com.xinchuang.service.image.ImageEditingService;
import com.xinchuang.service.image.TaskRunService;
import com.xinchuang.util.DeoUtil;
import com.xinchuang.util.FileElseUtil;
import com.xinchuang.util.LngLatUtil;
import com.xinchuang.util.RedisUtil;
import com.xinchuang.utils.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tools.ant.taskdefs.condition.Http;
import org.gdal.gdal.Band;
import org.gdal.gdal.Dataset;
import org.gdal.gdal.Driver;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconst;
import org.gdal.gdalconst.gdalconstConstants;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.GridFormatFinder;
import org.geotools.gce.geotiff.GeoTiffFormat;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.referencing.crs.DefaultProjectedCRS;
import org.geotools.util.factory.Hints;
import org.locationtech.jts.geom.Coordinate;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.*;
import java.util.List;

/**
 * TODO
 *
 * @author zkwczx
 * @version 1.0
 * @date 2023/9/19 17:29
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class GDALServiceImpl implements GDALService {

    private final KeyWord keyWord;

    private final KeyWordSystem keyWordSystem;

    private final ImageEditingService imageEditingService;

    private final ImageCutService imageCutService;

    private final ImgTargetTableService imgTargetTableService;

    private final TaskRunMapper taskRunMapper;

    private SnowflakeGenerator snow = new SnowflakeGenerator(0, 0);

    @Value("${info-trans.profile}")
    private String fileDir;

    private final RedisUtil redisUtil;

    @Override
    public void tif2DB(String tifFilePath, String id) {
        String dbPath = keyWord.getRootDir() + keyWord.getDbDir() + File.separator + id + ".idb";
        FileUtil.mkdir(keyWord.getRootDir() + keyWord.getDbDir());
        DBUtils.copyFileByTemplate(DBUtils.TILE_TEMPLATE, dbPath);
        File tifFile = new File(tifFilePath);
        try (FileInputStream fis = new FileInputStream(tifFile)) {
            BufferedImage image = ImageIO.read(fis);
            final int height = image.getHeight();
            final int width = image.getWidth();
            int x1 = 1;
            int y1 = 2;
            int z1 = 2;
            final int h = get256(height);
            final int w = get256(width);
            int i1 = getBig(h, w);
            final int n = 256;
            while (i1 >= n) {
                int rows;
                if (height % i1 == 0) {
                    rows = height / i1;
                } else {
                    rows = height / i1 + 1;
                }
                int cols;
                if (width % i1 == 0) {
                    cols = width / i1 + 1;
                } else {
                    cols = width / i1 + 1;
                }
                log.info(z1 + "层共" + rows * cols + "张");
                for (int x = 0; x < rows; x++) {
                    for (int y = 0; y < cols; y++) {
                        cut(id, dbPath, image, x1, y1, z1, i1, n, x, y);
                    }
                }
                i1 /= 2;
                x1 *= 2;
                y1 *= 2;
                z1++;
            }
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("rotation", 0);
            jsonObject.put("position", new double[]{23, 56});
            jsonObject.put("zoom", 4);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void cut(String id, String dbPath, BufferedImage image, int x1, int y1, int z1, int i1, int n, int x, int y) throws IOException {
        BufferedImage bufferedImage = new BufferedImage(n, n, BufferedImage.TYPE_INT_RGB);

        Graphics2D gr = bufferedImage.createGraphics();
        bufferedImage = gr.getDeviceConfiguration().createCompatibleImage(n, n, Transparency.TRANSLUCENT);
        gr = bufferedImage.createGraphics();
        gr.drawImage(image, 0, 0, n, n, i1 * y, i1 * x, i1 * y + i1, i1 * x + i1, null);
        gr.dispose();
        String pngPath = keyWord.getRootDir() + keyWord.getOutputDir() + File.separator + id + File.separator + z1 + "-" + (y + y1) + "-" + (x + x1) + ".png";
        File file = new File(pngPath);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        ImageIO.write(bufferedImage, "png", file);
        try (InputStream inputStream = new FileInputStream(pngPath)) {
            byte[] imgBytes = IOUtils.toByteArray(inputStream);
            String quadKey = MercatorWmtsUtils.xyzToQuadKey(y + y1, x + x1, z1);
            DBUtils.save(dbPath, imgBytes, quadKey);
        } catch (IOException | SQLException e) {
            log.error(e.getMessage(), e);
            return;
        }
    }

    @Async
    @Override
    public void tif2DB2(String id, int type, ImageEditing imageEditing) {
        String tifFile = null;
//        if (type == 1) {
//            tifFile = fileDir + imageEditing.getImgUrl();
//        } else {
//            tifFile = fileDir + imageEditing.getReferenceImg();
//        }
        int status = ImageEditingEnum.START.getCode();
        try {
            String iconUrl = "/icon/" + id + "/";
            FileUtil.mkdir(fileDir + iconUrl);
//            if (type == 1) {
//                imageEditing.setImgUrl(tifFile);
//                CommonUtil.generateThumbnail(tifFile, fileDir + iconUrl + "new_zc.jpg", 200, 200);
//                imageEditing.setImgThumb(iconUrl + "new_zc.jpg");
//            } else {
//                imageEditing.setReferenceImg(tifFile);
//                CommonUtil.generateThumbnail(tifFile, fileDir + iconUrl + "standard.jpg", 200, 200);
//                imageEditing.setReferenceThumb(iconUrl + "standard.jpg");
//            }
            String dbPath = fileDir + "/cutOut/" + id + ".idb";
            FileUtil.del(dbPath);
            DBUtils.copyFileByTemplate(DBUtils.TILE_TEMPLATE, dbPath);
            GridCoverage2D gridCoverage = GetGridCoverage2D(tifFile);
            if (null == gridCoverage) {
                log.error("文件不支持切图");
                status = ImageEditingEnum.FILE_ERROR.getCode();
                return;
            }
            boolean isTransform = false;
            CoordinateReferenceSystem crs = gridCoverage.getCoordinateReferenceSystem();
            if (crs instanceof DefaultProjectedCRS) {
                isTransform = true;
            } else if (!(crs instanceof DefaultGeographicCRS)) {
                log.error("文件类型不匹配" + crs.getClass());
                status = ImageEditingEnum.FILE_TYPE_ERROR.getCode();
                return;
            }
            String code = null;
            try {
                code = CRS.lookupIdentifier(crs, true);
            } catch (FactoryException e) {
                e.printStackTrace();
            }
            System.out.println("EPSG code:" + code);
            if (isTransform && StringUtils.isBlank(code)) {
                log.error("该影像坐标系异常" + crs.getClass());
                status = ImageEditingEnum.UNKNOWN_COORDINATE.getCode();
                return;
            }
            Dataset dataset = gdal.Open(tifFile, gdalconstConstants.GA_ReadOnly);
            if (ObjectUtils.isEmpty(dataset)) {
                log.error(gdal.GetLastErrorNo() + "===" + gdal.GetLastErrorMsg());
            }
            try {
                double[] geoTransform = dataset.GetGeoTransform();
                double[] defaultGetGeoTransform = {0, 1, 0, 0, 0, 1};
                if (Arrays.equals(geoTransform, defaultGetGeoTransform)) {
                    log.error("图像不含地理坐标信息");
                    status = ImageEditingEnum.NOT_GEOGRAPHIC_DATA.getCode();
                    return;
                }
                int xSize = dataset.getRasterXSize();
                int ySize = dataset.getRasterYSize();
                double lngMin = geoTransform[0];
                double angleX = geoTransform[2];
                double latMax = geoTransform[3];
                double lngMax = lngMin + (xSize * geoTransform[1]) + (ySize * angleX);
                double latMin = latMax + (xSize * geoTransform[4]) + (ySize * geoTransform[5]);
                if (isTransform && StringUtils.isNotBlank(code)) {
                    CoordinateReferenceSystem sourceCRS = CRS.decode(code);
                    CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326");
                    MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, false);
                    Coordinate lngLatMax = JTS.transform(new Coordinate(lngMax, latMax), null, transform);
                    Coordinate lngLatMin = JTS.transform(new Coordinate(lngMin, latMin), null, transform);
                    lngMax = lngLatMax.getY();
                    latMax = lngLatMax.getX();
                    lngMin = lngLatMin.getY();
                    latMin = lngLatMin.getX();
                }
                System.out.println(lngMax + "===" + lngMin + "===" + latMax + "===" + latMin);
//                if (type == 1) {
//                    imageEditing.setImgCenter(MercatorWmtsUtils.getCutCenter(lngMin, lngMax, latMin, latMax));
//                } else {
//                    imageEditing.setReferenceCenter(MercatorWmtsUtils.getCutCenter(lngMin, lngMax, latMin, latMax));
//                }
                double srcWePixelResolution = (lngMax - lngMin) / xSize;
                double srcNsPixelResolution = (latMax - latMin) / ySize;
                status = ImageEditingEnum.RUNNING.getCode();
                int zoom = 1;
                for (; zoom <= 20; zoom++) {
                    int[] tilePointMax = MercatorWmtsUtils.coordinates2tile(lngMax, latMax, zoom);
                    int[] tilePointMin = MercatorWmtsUtils.coordinates2tile(lngMin, latMin, zoom);
                    int tileRowMax = tilePointMin[1];
                    int tileColMax = tilePointMax[0];
                    int tileRowMin = tilePointMax[1];
                    int tileColMin = tilePointMin[0];
                    if (tileRowMax - tileRowMin + 1 < 4 || tileColMax - tileColMin + 1 < 4) {
                        continue;
                    }
                    double resolution = 180d / Math.pow(2, 7 + zoom);
                    if (resolution < srcWePixelResolution) {
                        break;
                    }
                    log.info("共有" + (tileRowMax - tileRowMin + 1) * (tileColMax - tileColMin + 1) + "张");
                    for (int row = tileRowMin; row <= tileRowMax; row++) {
                        for (int col = tileColMin; col <= tileColMax; col++) {
                            double tempLatMin = MercatorWmtsUtils.tile2lat(row + 1, zoom);
                            double tempLatMax = MercatorWmtsUtils.tile2lat(row, zoom);
                            double tempLonMin = MercatorWmtsUtils.tile2lng(col, zoom);
                            double tempLonMax = MercatorWmtsUtils.tile2lng(col + 1, zoom);
                            ReferencedEnvelope tileBound = new ReferencedEnvelope(tempLonMin, tempLonMax, tempLatMin, tempLatMax, DefaultGeographicCRS.WGS84);
                            ReferencedEnvelope imageBound = new ReferencedEnvelope(lngMin, lngMax, latMin, latMax, DefaultGeographicCRS.WGS84);
                            ReferencedEnvelope intersect = tileBound.intersection(imageBound);
                            double dstWePixelResolution = (tempLonMax - tempLonMin) / MercatorWmtsUtils.TILE_SIZE;
                            double dstNsPixelResolution = (tempLatMax - tempLatMin) / MercatorWmtsUtils.TILE_SIZE;
                            int offsetX = (int) ((intersect.getMinX() - lngMin) / srcWePixelResolution);
                            int offsetY = (int) Math.abs((intersect.getMaxY() - latMax) / srcNsPixelResolution);
                            int blockXSize = (int) ((intersect.getMaxX() - intersect.getMinX()) / srcWePixelResolution);
                            int blockYSize = (int) ((intersect.getMaxY() - intersect.getMinY()) / srcNsPixelResolution);
                            int imageXBuf = (int) Math.ceil((intersect.getMaxX() - intersect.getMinX()) / dstWePixelResolution);
                            int imageYBuf = (int) Math.ceil(Math.abs((intersect.getMaxY() - intersect.getMinY()) / dstNsPixelResolution));
                            int imageOffsetX = (int) ((intersect.getMinX() - tempLonMin) / dstWePixelResolution);
                            int imageOffsetY = (int) Math.abs((intersect.getMaxY() - tempLatMax) / dstNsPixelResolution);
                            imageOffsetX = imageOffsetX > 0 ? imageOffsetX : 0;
                            imageOffsetY = imageOffsetY > 0 ? imageOffsetY : 0;
                            Band inBand1 = dataset.GetRasterBand(1);
                            Band inBand2 = dataset.GetRasterBand(2);
                            Band inBand3 = dataset.GetRasterBand(3);
                            int[] band1BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            int[] band2BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            int[] band3BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            inBand1.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band1BuffData, 0, 0);
                            inBand2.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band2BuffData, 0, 0);
                            inBand3.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band3BuffData, 0, 0);
                            Driver memDriver = gdal.GetDriverByName("MEM");
                            Dataset msmDS = memDriver.Create("msmDS", 256, 256, 4);
                            Band dstBand1 = msmDS.GetRasterBand(1);
                            Band dstBand2 = msmDS.GetRasterBand(2);
                            Band dstBand3 = msmDS.GetRasterBand(3);
                            Band alphaBand = msmDS.GetRasterBand(4);
                            int[] alphaData = new int[256 * 256 * gdalconst.GDT_Int32];
                            for (int index = 0; index < alphaData.length; index++) {
                                if (band1BuffData[index] > 0) {
                                    alphaData[index] = 255;
                                }
                            }
                            dstBand1.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band1BuffData);
                            dstBand2.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band2BuffData);
                            dstBand3.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band3BuffData);
                            alphaBand.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, alphaData);

                            String pngPath = keyWord.getRootDir() + keyWord.getOutputDir() + File.separator + id + File.separator + zoom + "-" + col + "-" + row + ".png";
                            File file = new File(pngPath);
                            if (!file.getParentFile().exists()) {
                                file.getParentFile().mkdirs();
                            }

                            Driver pngDriver = gdal.GetDriverByName("PNG");
                            Dataset pngDs = pngDriver.CreateCopy(pngPath, msmDS);
                            msmDS.FlushCache();
                            msmDS.delete();
                            try (InputStream fis = new FileInputStream(pngPath)) {
                                byte[] imgBytes = IOUtils.toByteArray(fis);
                                String quadKey = MercatorWmtsUtils.xyzToQuadKey(col, row, zoom);
                                DBUtils.save(dbPath, imgBytes, quadKey);
                            } catch (IOException e) {
                                log.error(e.getMessage(), e);
                            }
                            pngDs.delete();
                        }
                    }
                }
                status = ImageEditingEnum.SUCCESS.getCode();
            } catch (Exception e) {
                e.printStackTrace();
                status = ImageEditingEnum.DEFAULT.getCode();
                return;
            } finally {
                dataset.delete();
            }
        } finally {
            LambdaUpdateWrapper<ImageEditing> updateWrap = new LambdaUpdateWrapper<>();
//            if (type == 1) {
//                updateWrap.set(ImageEditing::getImgThumb, imageEditing.getImgThumb());
//                updateWrap.set(ImageEditing::getImgStatus, status);
//                updateWrap.set(ImageEditing::getImgCenter, imageEditing.getImgCenter());
//            } else {
//                updateWrap.set(ImageEditing::getReferenceThumb, imageEditing.getReferenceThumb());
//                updateWrap.set(ImageEditing::getReferenceStatus, status);
//                updateWrap.set(ImageEditing::getReferenceCenter, imageEditing.getReferenceCenter());
//            }
            updateWrap.eq(ImageEditing::getId, imageEditing.getId());
            imageEditingService.update(null, updateWrap);
        }
    }

    @Override
    public Map<String,String> tifCutLonLat(String id, String tifFile, int type) {
        Map<String,String> resultMap = new HashMap<>();
        resultMap.put("code", "0");
        resultMap.put("msg", "");
        try {
            String cutId = snow.next() + "";
            String dbPath = fileDir + "/cutOut/" + cutId + ".idb";
            FileUtil.del(dbPath);
            DBUtils.copyFileByTemplate(DBUtils.TILE_TEMPLATE, dbPath);
            GridCoverage2D gridCoverage = GetGridCoverage2D(fileDir + tifFile);
            if (null == gridCoverage) {
                resultMap.put("msg", "当前文件不支持切图，请更换影像");
                return resultMap;
            }
            boolean isTransform = false;
            CoordinateReferenceSystem crs = gridCoverage.getCoordinateReferenceSystem();
            if (crs instanceof DefaultProjectedCRS) {
                isTransform = true;
            } else if (!(crs instanceof DefaultGeographicCRS)) {
                resultMap.put("msg", "当前文件类型不匹配，请更换影像");
                return resultMap;
            }
            String code = null;
            try {
                code = CRS.lookupIdentifier(crs, true);
            } catch (FactoryException e) {
                e.printStackTrace();
            }
            System.out.println("EPSG code:" + code);
            if (isTransform && StringUtils.isBlank(code)) {
                resultMap.put("msg", "当前影像坐标系异常，请更换影像");
                return resultMap;
            }
            Dataset dataset = gdal.Open(fileDir + tifFile, gdalconstConstants.GA_ReadOnly);
            if (ObjectUtils.isEmpty(dataset)) {
                log.error(gdal.GetLastErrorNo() + "===" + gdal.GetLastErrorMsg());
                resultMap.put("msg", "当前文件类型不匹配，请更换影像");
                return resultMap;
            }
            try {
                double[] geoTransform = dataset.GetGeoTransform();
                double[] defaultGetGeoTransform = {0, 1, 0, 0, 0, 1};
                if (Arrays.equals(geoTransform, defaultGetGeoTransform)) {
                    resultMap.put("msg", "当前影像未包含地理坐标信息，请更换影像");
                    return resultMap;
                }
                int xSize = dataset.getRasterXSize();
                int ySize = dataset.getRasterYSize();
                double lngMin = geoTransform[0];
                double angleX = geoTransform[2];
                double latMax = geoTransform[3];
                double lngMax = lngMin + (xSize * geoTransform[1]) + (ySize * angleX);
                double latMin = latMax + (xSize * geoTransform[4]) + (ySize * geoTransform[5]);
                if (isTransform && StringUtils.isNotBlank(code)) {
                    CoordinateReferenceSystem sourceCRS = CRS.decode(code);
                    CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326");
                    MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, false);
                    Coordinate lngLatMax = JTS.transform(new Coordinate(lngMax, latMax), null, transform);
                    Coordinate lngLatMin = JTS.transform(new Coordinate(lngMin, latMin), null, transform);
                    lngMax = lngLatMax.getY();
                    latMax = lngLatMax.getX();
                    lngMin = lngLatMin.getY();
                    latMin = lngLatMin.getX();
                }
                System.out.println("影像四角点坐标：" + lngMax + "===" + lngMin + "===" + latMax + "===" + latMin);
                JSONArray position = MercatorWmtsUtils.getCutCenterByArr(lngMin, lngMax, latMin, latMax);
                double srcWePixelResolution = (lngMax - lngMin) / xSize;
                double srcNsPixelResolution = (latMax - latMin) / ySize;
                int zoom = 1;
                for (; zoom <= 20; zoom++) {
                    int[] tilePointMax = MercatorWmtsUtils.coordinates2tile(lngMax, latMax, zoom);
                    int[] tilePointMin = MercatorWmtsUtils.coordinates2tile(lngMin, latMin, zoom);
                    int tileRowMax = tilePointMin[1];
                    int tileColMax = tilePointMax[0];
                    int tileRowMin = tilePointMax[1];
                    int tileColMin = tilePointMin[0];
                    if (tileRowMax - tileRowMin + 1 < 4 || tileColMax - tileColMin + 1 < 4) {
                        continue;
                    }
                    double resolution = 180d / Math.pow(2, 7 + zoom);
                    if (resolution < srcWePixelResolution) {
                        break;
                    }
                    log.info("共有" + (tileRowMax - tileRowMin + 1) * (tileColMax - tileColMin + 1) + "张");
                    for (int row = tileRowMin; row <= tileRowMax; row++) {
                        for (int col = tileColMin; col <= tileColMax; col++) {
                            double tempLatMin = MercatorWmtsUtils.tile2lat(row + 1, zoom);
                            double tempLatMax = MercatorWmtsUtils.tile2lat(row, zoom);
                            double tempLonMin = MercatorWmtsUtils.tile2lng(col, zoom);
                            double tempLonMax = MercatorWmtsUtils.tile2lng(col + 1, zoom);
                            ReferencedEnvelope tileBound = new ReferencedEnvelope(tempLonMin, tempLonMax, tempLatMin, tempLatMax, DefaultGeographicCRS.WGS84);
                            ReferencedEnvelope imageBound = new ReferencedEnvelope(lngMin, lngMax, latMin, latMax, DefaultGeographicCRS.WGS84);
                            ReferencedEnvelope intersect = tileBound.intersection(imageBound);
                            double dstWePixelResolution = (tempLonMax - tempLonMin) / MercatorWmtsUtils.TILE_SIZE;
                            double dstNsPixelResolution = (tempLatMax - tempLatMin) / MercatorWmtsUtils.TILE_SIZE;
                            int offsetX = (int) ((intersect.getMinX() - lngMin) / srcWePixelResolution);
                            int offsetY = (int) Math.abs((intersect.getMaxY() - latMax) / srcNsPixelResolution);
                            int blockXSize = (int) ((intersect.getMaxX() - intersect.getMinX()) / srcWePixelResolution);
                            int blockYSize = (int) ((intersect.getMaxY() - intersect.getMinY()) / srcNsPixelResolution);
                            int imageXBuf = (int) Math.ceil((intersect.getMaxX() - intersect.getMinX()) / dstWePixelResolution);
                            int imageYBuf = (int) Math.ceil(Math.abs((intersect.getMaxY() - intersect.getMinY()) / dstNsPixelResolution));
                            int imageOffsetX = (int) ((intersect.getMinX() - tempLonMin) / dstWePixelResolution);
                            int imageOffsetY = (int) Math.abs((intersect.getMaxY() - tempLatMax) / dstNsPixelResolution);
                            imageOffsetX = imageOffsetX > 0 ? imageOffsetX : 0;
                            imageOffsetY = imageOffsetY > 0 ? imageOffsetY : 0;
                            Band inBand1 = dataset.GetRasterBand(1);
                            Band inBand2 = dataset.GetRasterBand(2);
                            Band inBand3 = dataset.GetRasterBand(3);
                            int[] band1BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            int[] band2BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            int[] band3BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            inBand1.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band1BuffData, 0, 0);
                            inBand2.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band2BuffData, 0, 0);
                            inBand3.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band3BuffData, 0, 0);
                            Driver memDriver = gdal.GetDriverByName("MEM");
                            Dataset msmDS = memDriver.Create("msmDS", 256, 256, 4);
                            Band dstBand1 = msmDS.GetRasterBand(1);
                            Band dstBand2 = msmDS.GetRasterBand(2);
                            Band dstBand3 = msmDS.GetRasterBand(3);
                            Band alphaBand = msmDS.GetRasterBand(4);
                            int[] alphaData = new int[256 * 256 * gdalconst.GDT_Int32];
                            for (int index = 0; index < alphaData.length; index++) {
                                if (band1BuffData[index] > 0) {
                                    alphaData[index] = 255;
                                }
                            }
                            dstBand1.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band1BuffData);
                            dstBand2.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band2BuffData);
                            dstBand3.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band3BuffData);
                            alphaBand.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, alphaData);

                            String pngPath = keyWord.getRootDir() + keyWord.getOutputDir() + File.separator + cutId + File.separator + zoom + "-" + col + "-" + row + ".png";
                            File file = new File(pngPath);
                            if (!file.getParentFile().exists()) {
                                file.getParentFile().mkdirs();
                            }

                            Driver pngDriver = gdal.GetDriverByName("PNG");
                            Dataset pngDs = pngDriver.CreateCopy(pngPath, msmDS);
                            msmDS.FlushCache();
                            msmDS.delete();
                            try (InputStream fis = new FileInputStream(pngPath)) {
                                byte[] imgBytes = IOUtils.toByteArray(fis);
                                String quadKey = MercatorWmtsUtils.xyzToQuadKey(col, row, zoom);
                                DBUtils.save(dbPath, imgBytes, quadKey);
                            } catch (IOException e) {
                                log.error("切图异常" + e.getMessage(), e);
                                String error = "ERROR 5: Illegal values for buffer size";
                                if (e.getMessage().equals(error)) {
                                    pngDs.delete();
                                    break;
                                }
                            }
                            pngDs.delete();
                        }
                    }
                }
                if (type == ImageCutEnum.CUT.getType()) {
                    imageCutService.remove(new LambdaUpdateWrapper<ImageCut>()
                            .eq(ImageCut::getImageType, ImageCutEnum.CUT.getType())
                            .eq(ImageCut::getRedId, id));
                }
                ImageCut imageCut = new ImageCut();
                imageCut.setId(cutId);
                imageCut.setRedId(id);
                imageCut.setImageType(type + "");
                imageCut.setImageUrl(tifFile);
                imageCut.setPosition(position.toJSONString());
                imageCut.setLon(position.getString(0));
                imageCut.setLat(position.getString(1));
                FileUtil.mkdir(fileDir + "/image/thumb");
                CommonUtil.getImage(fileDir + tifFile, fileDir + "/image/thumb/" + cutId + ".jpg");
                imageCut.setImage("/image/thumb/" + cutId + ".jpg");
                CommonUtil.generateThumbnail(fileDir + tifFile, fileDir + "/image/thumb/" + cutId + "_thumb.jpg", 200, 200);
                imageCut.setThumb("/image/thumb/" + cutId + "_thumb.jpg");
                imageCut.setRemark("专题图片");
                imageCut.setMinLon(lngMin + "");
                imageCut.setMinLat(latMin + "");
                imageCut.setMaxLon(lngMax + "");
                imageCut.setMaxLat(latMax + "");
                imageCutService.save(imageCut);
                resultMap.put("code", cutId);
                resultMap.put("msg", position.toJSONString());
                return resultMap;
            }  finally {
                dataset.delete();
            }
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("msg", "系统异常，请稍后重试");
        }
        return resultMap;
    }

//    @Async
//    @Override
//    public void tifToImage(String id, String redId, String tifFile, String remark, int type) {
//        String cut = cut(redId, tifFile, type, remark);
//        if (cut.length() == 1) {
//            imgTargetTableService.lambdaUpdate()
//                    .set(ImgTargetTable::getStatus, cut)
//                    .set(ImgTargetTable::getUpdateTime, new Date())
//                    .eq(ImgTargetTable::getImgId, id);
//        } else {
//            imgTargetTableService.lambdaUpdate()
//                    .set(ImgTargetTable::getStatus, "4")
//                    .set(ImgTargetTable::getUpdateTime, new Date())
//                    .eq(ImgTargetTable::getImgId, id);
//        }
//    }

    @Override
    public String tifPoints(TaskRun taskRun, JSONArray positionOne, JSONArray positionTwo) {
        ImageCut newId = imageCutService.getById(taskRun.getBaseId());
        ImageCut baseId = imageCutService.getById(taskRun.getNewId());
        String url = keyWordSystem.getPythonUrl();
        String post = RunExeUtil.getPointPost(
                url,
                keyWordSystem.getFILE_URL(),
                newId.getImageUrl(),
                baseId.getImageUrl(),
                taskRun.getId(),
                positionOne,
                positionTwo
        );
        if (StringUtils.isNotBlank(post)) {
            String cut = cut(taskRun.getTaskId(), post + "res.tif", ImageTypeConstant.POINTVIEW, "选点匹配");
            if (cut.length() > 1) {
                taskRun.setResultId(cut);
                taskRun.setTaskStatus("DONE");
                taskRun.setResultUrl("/file/point/" + taskRun.getId() + "/");
                taskRunMapper.insert(taskRun);
                return cut;
            }
        }
        return "";
    }

    @Override
    public JSONObject autoDiscern(ImageCut cut, JSONArray array) {
        JSONObject toDiscern = MyUtil.toDiscern(array);
        System.out.println("toDiscern:" + toDiscern);
        String fileUrl = keyWordSystem.getFILE_URL() + "/file/discern/" + DateUtil.format(new Date(), "yyyyMMddHHmmssS");
        FileUtil.mkdir(fileUrl);
        FileUtil.writeString(toDiscern.toJSONString(), fileUrl + "/rectangle.json", "UTF-8");
        JSONObject resultJson = new JSONObject();
        resultJson.put("image_path", keyWordSystem.getFILE_URL() + cut.getImageUrl());
        resultJson.put("json_input_path", fileUrl + "/rectangle.json");
        String url = keyWordSystem.getPointUrl() + "/detection";
        HttpResponse execute = HttpUtil.createRequest(Method.POST, url)
                .body(resultJson.toJSONString())
                .timeout(1000 * 60 * 5)
                .execute();
        if (execute.getStatus() == HttpStatus.HTTP_OK) {
            return JSONObject.parseObject(execute.body());
        } else {
            return null;
        }
    }

    @Override
    public boolean toWGS84(String sourceUrl, String targetUrl) {
        JSONObject resultJson = new JSONObject();
        resultJson.put("input_path", sourceUrl);
        resultJson.put("output_path", targetUrl);
        String url = keyWordSystem.getPointUrl() + "/toWGS84";
        HttpResponse execute = HttpUtil.createRequest(Method.POST, url)
                .body(resultJson.toJSONString())
                .timeout(1000 * 60 * 5)
                .execute();
        if (execute.getStatus() == HttpStatus.HTTP_OK) {
            return true;
        } else {
            return false;
        }
    }


    @Async
    @Override
    public void tifCut(String redId, String tifFile, int type, String remark) {
        String cut = cut(redId, tifFile, type, remark);
    }

    public static JSONArray getTifCenterLngLat(String tifFile, ImgTargetTable imgTargetTable, boolean isTure, double lng, double lat) {
        GridCoverage2D gridCoverage = get2D(tifFile);
        if (null == gridCoverage) {
            return new JSONArray();
        }
        boolean isTransform = false;
        CoordinateReferenceSystem crs = gridCoverage.getCoordinateReferenceSystem();
        if (crs instanceof DefaultProjectedCRS) {
            isTransform = true;
        } else if (!(crs instanceof DefaultGeographicCRS)) {
            return new JSONArray();
        }
        String code = null;
        try {
            code = CRS.lookupIdentifier(crs, true);
        } catch (FactoryException e) {
            return new JSONArray();
        }
        System.out.println("EPSG code:" + code);
        if (isTransform && StringUtils.isBlank(code)) {
            return new JSONArray();
        }
        System.out.println("打开文件:" + tifFile);
//        System.out.println(gdalconstConstants.GA_ReadOnly);
        Dataset dataset = gdal.Open(tifFile, 0);
        if (ObjectUtils.isEmpty(dataset)) {
            log.error(gdal.GetLastErrorNo() + "===" + gdal.GetLastErrorMsg());
            return new JSONArray();
        }
        try {
            double[] geoTransform = dataset.GetGeoTransform();
            double[] defaultGetGeoTransform = {0, 1, 0, 0, 0, 1};
            if (Arrays.equals(geoTransform, defaultGetGeoTransform)) {
                return new JSONArray();
            }
            int xSize = dataset.getRasterXSize();
            int ySize = dataset.getRasterYSize();
            double lngMin = geoTransform[0];
            double angleX = geoTransform[2];
            double latMax = geoTransform[3];
            double lngMax = lngMin + (xSize * geoTransform[1]) + (ySize * angleX);
            double latMin = latMax + (xSize * geoTransform[4]) + (ySize * geoTransform[5]);
            if (isTransform && StringUtils.isNotBlank(code)) {
                CoordinateReferenceSystem sourceCRS = CRS.decode(code);
                CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326");
                MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, false);
                Coordinate lngLatMax = JTS.transform(new Coordinate(lngMax, latMax), null, transform);
                Coordinate lngLatMin = JTS.transform(new Coordinate(lngMin, latMin), null, transform);
                lngMax = lngLatMax.getY();
                latMax = lngLatMax.getX();
                lngMin = lngLatMin.getY();
                latMin = lngLatMin.getX();
            }
            LngLatUtil.Position position1 = new LngLatUtil.Position(latMax, lngMin);
            LngLatUtil.Position position2 = new LngLatUtil.Position(latMin, lngMax);
            LinkedList<LngLatUtil.Position> postionList = new LinkedList<>();
            postionList.add(position1);
            postionList.add(position2);
            Map<String, Double> point = LngLatUtil.getCenterPoint(postionList);

            JSONArray array1 = null;
            if (isTure) {
                array1 = new JSONArray();
                array1.add(lngMin);
                array1.add(latMax);
                array1.add(lngMax);
                array1.add(latMin);
                imgTargetTable.setLon(point.get("centerLon") + "");
                imgTargetTable.setLat(point.get("centerLat") + "");
                imgTargetTable.setPosition("[\"" + point.get("centerLon") + "\",\"" + point.get("centerLat") + "\"]");
            } else {
                array1 = CenterUtil.getArray(point.get("centerLon"), point.get("centerLat"), lng, lat, lngMin, latMax, lngMax, latMin);
                imgTargetTable.setLon(lng + "");
                imgTargetTable.setLat(lat + "");
                imgTargetTable.setPosition("[\"" + lng + "\",\"" + lat + "\"]");
            }

//            //计算移动的方位角
//            double angle = DeoUtil.getBearingAngle(point.get("centerLat"), point.get("centerLon"), lat, lng);
//            log.info(point.get("centerLon") + "," + point.get("centerLat"));
//            log.info(lngMin + "," + latMax);
//            log.info(lngMax + "," + latMin);
//            //获取两个点位的距离
//            double distance = LngLatUtil.getDistance(lng, lat, point.get("centerLon"), point.get("centerLat"));
//            log.info(angle + "");
//            log.info(distance + "");
//            //计算移动后的矩形对角点坐标
//            List<Double> doubles1 = DeoUtil.computerThatLonLat(lngMin, latMax, angle, distance * 1000);
//            List<Double> doubles2 = DeoUtil.computerThatLonLat(lngMax, latMin, angle, distance * 1000);
//            log.info(lng + "," + lat);
//            log.info(doubles1.get(0) + "," + doubles1.get(1));
//            log.info(doubles2.get(0) + "," + doubles2.get(1));
//            log.info(DeoUtil.getBearingAngle(latMax, lngMin, doubles1.get(1), doubles1.get(0)) + "");
//            JSONArray array = new JSONArray();
//            array.add(doubles1.get(0));
//            array.add(doubles1.get(1));
//            array.add(doubles2.get(0));
//            array.add(doubles2.get(1));
            return array1;
        } catch (Exception e) {
            return new JSONArray();
        }
    }

    @Override
    public ImageCut tif(String redId, String tifFile, int type, String remark) {
        try {
            String cutId = snow.next() + "";
            String dbPath = fileDir + "/cutOut/" + cutId + ".idb";
            FileUtil.del(dbPath);
            DBUtils.copyFileByTemplate(DBUtils.TILE_TEMPLATE, dbPath);
            GridCoverage2D gridCoverage = GetGridCoverage2D(fileDir + tifFile);
            if (null == gridCoverage) {
                return null;
            }
            boolean isTransform = false;
            CoordinateReferenceSystem crs = gridCoverage.getCoordinateReferenceSystem();
            if (crs instanceof DefaultProjectedCRS) {
                isTransform = true;
            } else if (!(crs instanceof DefaultGeographicCRS)) {
                return null;
            }
            String code = null;
            try {
                code = CRS.lookupIdentifier(crs, true);
            } catch (FactoryException e) {
                return null;
            }
            System.out.println("EPSG code:" + code);
            if (isTransform && StringUtils.isBlank(code)) {
                return null;
            }
            Dataset dataset = gdal.Open(fileDir + tifFile, gdalconstConstants.GA_ReadOnly);
            if (ObjectUtils.isEmpty(dataset)) {
                log.error(gdal.GetLastErrorNo() + "===" + gdal.GetLastErrorMsg());
                return null;
            }
            try {
                double[] geoTransform = dataset.GetGeoTransform();
                double[] defaultGetGeoTransform = {0, 1, 0, 0, 0, 1};
                if (Arrays.equals(geoTransform, defaultGetGeoTransform)) {
                    return null;
                }
                int xSize = dataset.getRasterXSize();
                int ySize = dataset.getRasterYSize();
                double lngMin = geoTransform[0];
                double angleX = geoTransform[2];
                double latMax = geoTransform[3];
                double lngMax = lngMin + (xSize * geoTransform[1]) + (ySize * angleX);
                double latMin = latMax + (xSize * geoTransform[4]) + (ySize * geoTransform[5]);
                if (isTransform && StringUtils.isNotBlank(code)) {
                    CoordinateReferenceSystem sourceCRS = CRS.decode(code);
                    CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326");
                    MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, false);
                    Coordinate lngLatMax = JTS.transform(new Coordinate(lngMax, latMax), null, transform);
                    Coordinate lngLatMin = JTS.transform(new Coordinate(lngMin, latMin), null, transform);
                    lngMax = lngLatMax.getY();
                    latMax = lngLatMax.getX();
                    lngMin = lngLatMin.getY();
                    latMin = lngLatMin.getX();
                }
                JSONArray position = MercatorWmtsUtils.getCutCenterByArr(lngMin, lngMax, latMin, latMax);
                double srcWePixelResolution = (lngMax - lngMin) / xSize;
                double srcNsPixelResolution = (latMax - latMin) / ySize;
                int zoom = 1;
                for (; zoom <= 20; zoom++) {
                    int[] tilePointMax = MercatorWmtsUtils.coordinates2tile(lngMax, latMax, zoom);
                    int[] tilePointMin = MercatorWmtsUtils.coordinates2tile(lngMin, latMin, zoom);
                    int tileRowMax = tilePointMin[1];
                    int tileColMax = tilePointMax[0];
                    int tileRowMin = tilePointMax[1];
                    int tileColMin = tilePointMin[0];
                    if (tileRowMax - tileRowMin + 1 < 4 || tileColMax - tileColMin + 1 < 4) {
                        continue;
                    }
                    double resolution = 180d / Math.pow(2, 7 + zoom);
                    if (resolution < srcWePixelResolution) {
                        break;
                    }
                    log.info("共有" + (tileRowMax - tileRowMin + 1) * (tileColMax - tileColMin + 1) + "张");
                    for (int row = tileRowMin; row <= tileRowMax; row++) {
                        for (int col = tileColMin; col <= tileColMax; col++) {
                            double tempLatMin = MercatorWmtsUtils.tile2lat(row + 1, zoom);
                            double tempLatMax = MercatorWmtsUtils.tile2lat(row, zoom);
                            double tempLonMin = MercatorWmtsUtils.tile2lng(col, zoom);
                            double tempLonMax = MercatorWmtsUtils.tile2lng(col + 1, zoom);
                            ReferencedEnvelope tileBound = new ReferencedEnvelope(tempLonMin, tempLonMax, tempLatMin, tempLatMax, DefaultGeographicCRS.WGS84);
                            ReferencedEnvelope imageBound = new ReferencedEnvelope(lngMin, lngMax, latMin, latMax, DefaultGeographicCRS.WGS84);
                            ReferencedEnvelope intersect = tileBound.intersection(imageBound);
                            double dstWePixelResolution = (tempLonMax - tempLonMin) / MercatorWmtsUtils.TILE_SIZE;
                            double dstNsPixelResolution = (tempLatMax - tempLatMin) / MercatorWmtsUtils.TILE_SIZE;
                            int offsetX = (int) ((intersect.getMinX() - lngMin) / srcWePixelResolution);
                            int offsetY = (int) Math.abs((intersect.getMaxY() - latMax) / srcNsPixelResolution);
                            int blockXSize = (int) ((intersect.getMaxX() - intersect.getMinX()) / srcWePixelResolution);
                            int blockYSize = (int) ((intersect.getMaxY() - intersect.getMinY()) / srcNsPixelResolution);
                            int imageXBuf = (int) Math.ceil((intersect.getMaxX() - intersect.getMinX()) / dstWePixelResolution);
                            int imageYBuf = (int) Math.ceil(Math.abs((intersect.getMaxY() - intersect.getMinY()) / dstNsPixelResolution));
                            int imageOffsetX = (int) ((intersect.getMinX() - tempLonMin) / dstWePixelResolution);
                            int imageOffsetY = (int) Math.abs((intersect.getMaxY() - tempLatMax) / dstNsPixelResolution);
                            imageOffsetX = imageOffsetX > 0 ? imageOffsetX : 0;
                            imageOffsetY = imageOffsetY > 0 ? imageOffsetY : 0;
                            Band inBand1 = dataset.GetRasterBand(1);
                            Band inBand2 = dataset.GetRasterBand(2);
                            Band inBand3 = dataset.GetRasterBand(3);
                            int[] band1BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            int[] band2BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            int[] band3BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            inBand1.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band1BuffData, 0, 0);
                            inBand2.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band2BuffData, 0, 0);
                            inBand3.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band3BuffData, 0, 0);
                            Driver memDriver = gdal.GetDriverByName("MEM");
                            Dataset msmDS = memDriver.Create("msmDS", 256, 256, 4);
                            Band dstBand1 = msmDS.GetRasterBand(1);
                            Band dstBand2 = msmDS.GetRasterBand(2);
                            Band dstBand3 = msmDS.GetRasterBand(3);
                            Band alphaBand = msmDS.GetRasterBand(4);
                            int[] alphaData = new int[256 * 256 * gdalconst.GDT_Int32];
                            for (int index = 0; index < alphaData.length; index++) {
                                if (band1BuffData[index] > 0) {
                                    alphaData[index] = 255;
                                }
                            }
                            dstBand1.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band1BuffData);
                            dstBand2.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band2BuffData);
                            dstBand3.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band3BuffData);
                            alphaBand.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, alphaData);

                            String pngPath = keyWord.getRootDir() + keyWord.getOutputDir() + File.separator + cutId + File.separator + zoom + "-" + col + "-" + row + ".png";
                            File file = new File(pngPath);
                            if (!file.getParentFile().exists()) {
                                file.getParentFile().mkdirs();
                            }

                            Driver pngDriver = gdal.GetDriverByName("PNG");
                            Dataset pngDs = pngDriver.CreateCopy(pngPath, msmDS);
                            msmDS.FlushCache();
                            msmDS.delete();
                            try (InputStream fis = new FileInputStream(pngPath)) {
                                byte[] imgBytes = IOUtils.toByteArray(fis);
                                String quadKey = MercatorWmtsUtils.xyzToQuadKey(col, row, zoom);
                                DBUtils.save(dbPath, imgBytes, quadKey);
                            } catch (IOException e) {
                                log.error("切图异常" + e.getMessage(), e);
                            }
                            pngDs.delete();
                        }
                    }
                }
                ImageCut imageCut = new ImageCut();
                imageCut.setId(cutId);
                imageCut.setRedId(redId);
                imageCut.setImageType(type + "");
                imageCut.setImageUrl(tifFile);
                imageCut.setPosition(position.toJSONString());
                imageCut.setLon(position.getString(0));
                imageCut.setLat(position.getString(1));
                FileUtil.mkdir(fileDir + "/image/thumb");
                CommonUtil.getImage(fileDir + tifFile, fileDir + "/image/thumb/" + cutId + ".jpg");
                imageCut.setImage("/image/thumb/" + cutId + ".jpg");
                CommonUtil.generateThumbnail(fileDir + tifFile, fileDir + "/image/thumb/" + cutId + "_thumb.jpg", 200, 200);
                imageCut.setThumb("/image/thumb/" + cutId + "_thumb.jpg");
                imageCut.setRemark(remark);
                imageCut.setMinLon(lngMin + "");
                imageCut.setMinLat(latMin + "");
                imageCut.setMaxLon(lngMax + "");
                imageCut.setMaxLat(latMax + "");
                imageCutService.save(imageCut);
                log.info("切图成功");
                return imageCut;
            }  finally {
                dataset.delete();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private String isWGS84(String tifFile) {
        String status = "0";
        GridCoverage2D gridCoverage = GetGridCoverage2D(fileDir + tifFile);
        if (null == gridCoverage) {
            status = CutEnum.NOT_CUT.getCode();
            return status;
        }
        String code = null;
        CoordinateReferenceSystem crs = gridCoverage.getCoordinateReferenceSystem();
        if (crs instanceof DefaultProjectedCRS) {

        } else if (!(crs instanceof DefaultGeographicCRS)) {
            status = CutEnum.BOT_CUT_TYPE.getCode();
            return status;
        }
        try {
            code = CRS.lookupIdentifier(crs, true);
        } catch (FactoryException e) {
            status = CutEnum.BOT_CUT_TYPE.getCode();
            return status;
        }
        System.out.println("EPSG code:" + code);
        if (!"EPSG:4326".equals(code)) {
            log.info("影像坐标系为：{}，需要转换", code);
            String targetUrl = "/toTif/" + UUID.randomUUID().toString() + tifFile.substring(tifFile.lastIndexOf("."));
            boolean toWGS84 = toWGS84(fileDir + tifFile, fileDir + targetUrl);
            if (!toWGS84) {
                status = CutEnum.BOT_CUT_TYPE.getCode();
                return status;
            }
            tifFile = targetUrl;
        }
        return tifFile;
    }

    private String cut(String redId, String tifFile, int type, String remark) {
        String status = "0";
        String redisKey = "REDIS_IMAGES_";
        if (0 == type) {
            redisKey += "BASE";
        } else if (1 == type) {
            redisKey += "NEW";
        } else {
            redisKey += "RESULT";
        }
        try {
            String cutId = snow.next() + "";
            String dbPath = fileDir + "/cutOut/" + cutId + ".idb";
            FileUtil.del(dbPath);
            String wgs84 = isWGS84(tifFile);
            if (!FileElseUtil.isDouble(wgs84)) {
                tifFile = wgs84;
            } else {
                return status;
            }
            log.info("切图影像地址为:{}", tifFile);
            DBUtils.copyFileByTemplate(DBUtils.TILE_TEMPLATE, dbPath);
            GridCoverage2D gridCoverage = GetGridCoverage2D(fileDir + tifFile);
            if (null == gridCoverage) {
                status = CutEnum.NOT_CUT.getCode();
                return status;
            }
            boolean isTransform = false;
            CoordinateReferenceSystem crs = gridCoverage.getCoordinateReferenceSystem();
            if (crs instanceof DefaultProjectedCRS) {
                isTransform = true;
            } else if (!(crs instanceof DefaultGeographicCRS)) {
                status = CutEnum.BOT_CUT_TYPE.getCode();
                return status;
            }
            String code = null;
            try {
                code = CRS.lookupIdentifier(crs, true);
            } catch (FactoryException e) {
                status = CutEnum.BOT_CUT_TYPE.getCode();
                return status;
            }
            System.out.println("EPSG code:" + code);
            if (isTransform && StringUtils.isBlank(code)) {
                status = CutEnum.NOT_CUT_POSITION.getCode();
                return status;
            }
            Dataset dataset = gdal.Open(fileDir + tifFile, gdalconstConstants.GA_ReadOnly);
            if (ObjectUtils.isEmpty(dataset)) {
                log.error(gdal.GetLastErrorNo() + "===" + gdal.GetLastErrorMsg());
                status = CutEnum.BOT_CUT_TYPE.getCode();
                return status;
            }
            try {
                double[] geoTransform = dataset.GetGeoTransform();
                double[] defaultGetGeoTransform = {0, 1, 0, 0, 0, 1};
                if (Arrays.equals(geoTransform, defaultGetGeoTransform)) {
                    status = CutEnum.NOT_CUT_POSITION.getCode();
                    return status;
                }
                int xSize = dataset.getRasterXSize();
                int ySize = dataset.getRasterYSize();
                double lngMin = geoTransform[0];
                double angleX = geoTransform[2];
                double latMax = geoTransform[3];
                double lngMax = lngMin + (xSize * geoTransform[1]) + (ySize * angleX);
                double latMin = latMax + (xSize * geoTransform[4]) + (ySize * geoTransform[5]);
                if (isTransform && StringUtils.isNotBlank(code)) {
                    CoordinateReferenceSystem sourceCRS = CRS.decode(code);
                    CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326");
                    MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, false);
                    Coordinate lngLatMax = JTS.transform(new Coordinate(lngMax, latMax), null, transform);
                    Coordinate lngLatMin = JTS.transform(new Coordinate(lngMin, latMin), null, transform);
                    lngMax = lngLatMax.getY();
                    latMax = lngLatMax.getX();
                    lngMin = lngLatMin.getY();
                    latMin = lngLatMin.getX();
                }
                JSONArray position = MercatorWmtsUtils.getCutCenterByArr(lngMin, lngMax, latMin, latMax);
                double srcWePixelResolution = (lngMax - lngMin) / xSize;
                double srcNsPixelResolution = (latMax - latMin) / ySize;
                int zoom = 1;
                for (; zoom <= 20; zoom++) {
                    int[] tilePointMax = MercatorWmtsUtils.coordinates2tile(lngMax, latMax, zoom);
                    int[] tilePointMin = MercatorWmtsUtils.coordinates2tile(lngMin, latMin, zoom);
                    int tileRowMax = tilePointMin[1];
                    int tileColMax = tilePointMax[0];
                    int tileRowMin = tilePointMax[1];
                    int tileColMin = tilePointMin[0];
                    if (tileRowMax - tileRowMin + 1 < 4 || tileColMax - tileColMin + 1 < 4) {
                        continue;
                    }
                    double resolution = 180d / Math.pow(2, 7 + zoom);
                    if (resolution < srcWePixelResolution) {
                        break;
                    }
                    log.info("共有" + (tileRowMax - tileRowMin + 1) * (tileColMax - tileColMin + 1) + "张");
                    for (int row = tileRowMin; row <= tileRowMax; row++) {
                        for (int col = tileColMin; col <= tileColMax; col++) {
                            double tempLatMin = MercatorWmtsUtils.tile2lat(row + 1, zoom);
                            double tempLatMax = MercatorWmtsUtils.tile2lat(row, zoom);
                            double tempLonMin = MercatorWmtsUtils.tile2lng(col, zoom);
                            double tempLonMax = MercatorWmtsUtils.tile2lng(col + 1, zoom);
                            ReferencedEnvelope tileBound = new ReferencedEnvelope(tempLonMin, tempLonMax, tempLatMin, tempLatMax, DefaultGeographicCRS.WGS84);
                            ReferencedEnvelope imageBound = new ReferencedEnvelope(lngMin, lngMax, latMin, latMax, DefaultGeographicCRS.WGS84);
                            ReferencedEnvelope intersect = tileBound.intersection(imageBound);
                            double dstWePixelResolution = (tempLonMax - tempLonMin) / MercatorWmtsUtils.TILE_SIZE;
                            double dstNsPixelResolution = (tempLatMax - tempLatMin) / MercatorWmtsUtils.TILE_SIZE;
                            int offsetX = (int) ((intersect.getMinX() - lngMin) / srcWePixelResolution);
                            int offsetY = (int) Math.abs((intersect.getMaxY() - latMax) / srcNsPixelResolution);
                            int blockXSize = (int) ((intersect.getMaxX() - intersect.getMinX()) / srcWePixelResolution);
                            int blockYSize = (int) ((intersect.getMaxY() - intersect.getMinY()) / srcNsPixelResolution);
                            int imageXBuf = (int) Math.ceil((intersect.getMaxX() - intersect.getMinX()) / dstWePixelResolution);
                            int imageYBuf = (int) Math.ceil(Math.abs((intersect.getMaxY() - intersect.getMinY()) / dstNsPixelResolution));
                            int imageOffsetX = (int) ((intersect.getMinX() - tempLonMin) / dstWePixelResolution);
                            int imageOffsetY = (int) Math.abs((intersect.getMaxY() - tempLatMax) / dstNsPixelResolution);
                            imageOffsetX = imageOffsetX > 0 ? imageOffsetX : 0;
                            imageOffsetY = imageOffsetY > 0 ? imageOffsetY : 0;
                            Band inBand1 = dataset.GetRasterBand(1);
                            Band inBand2 = dataset.GetRasterBand(2);
                            Band inBand3 = dataset.GetRasterBand(3);
                            int[] band1BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            int[] band2BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            int[] band3BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            inBand1.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band1BuffData, 0, 0);
                            inBand2.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band2BuffData, 0, 0);
                            inBand3.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band3BuffData, 0, 0);
                            Driver memDriver = gdal.GetDriverByName("MEM");
                            Dataset msmDS = memDriver.Create("msmDS", 256, 256, 4);
                            Band dstBand1 = msmDS.GetRasterBand(1);
                            Band dstBand2 = msmDS.GetRasterBand(2);
                            Band dstBand3 = msmDS.GetRasterBand(3);
                            Band alphaBand = msmDS.GetRasterBand(4);
                            int[] alphaData = new int[256 * 256 * gdalconst.GDT_Int32];
                            for (int index = 0; index < alphaData.length; index++) {
                                if (band1BuffData[index] > 0) {
                                    alphaData[index] = 255;
                                }
                            }
                            dstBand1.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band1BuffData);
                            dstBand2.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band2BuffData);
                            dstBand3.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band3BuffData);
                            alphaBand.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, alphaData);

                            String pngPath = keyWord.getRootDir() + keyWord.getOutputDir() + File.separator + cutId + File.separator + zoom + "-" + col + "-" + row + ".png";
                            File file = new File(pngPath);
                            if (!file.getParentFile().exists()) {
                                file.getParentFile().mkdirs();
                            }

                            Driver pngDriver = gdal.GetDriverByName("PNG");
                            Dataset pngDs = pngDriver.CreateCopy(pngPath, msmDS);
                            msmDS.FlushCache();
                            msmDS.delete();
                            try (InputStream fis = new FileInputStream(pngPath)) {
                                byte[] imgBytes = IOUtils.toByteArray(fis);
                                String quadKey = MercatorWmtsUtils.xyzToQuadKey(col, row, zoom);
                                DBUtils.save(dbPath, imgBytes, quadKey);
                            } catch (IOException e) {
                                log.error("切图异常" + e.getMessage(), e);
                            }
                            pngDs.delete();
                        }
                    }
                }
                ImageCut imageCut = new ImageCut();
                imageCut.setId(cutId);
                imageCut.setRedId(redId);
                imageCut.setImageType(type + "");
                imageCut.setImageUrl(tifFile);
                imageCut.setPosition(position.toJSONString());
                imageCut.setLon(position.getString(0));
                imageCut.setLat(position.getString(1));
                FileUtil.mkdir(fileDir + "/image/thumb");
                CommonUtil.getImage(fileDir + tifFile, fileDir + "/image/thumb/" + cutId + ".jpg");
                imageCut.setImage("/image/thumb/" + cutId + ".jpg");
                CommonUtil.generateThumbnail(fileDir + tifFile, fileDir + "/image/thumb/" + cutId + "_thumb.jpg", 200, 200);
                imageCut.setThumb("/image/thumb/" + cutId + "_thumb.jpg");
                imageCut.setRemark(remark);
                imageCut.setMinLon(lngMin + "");
                imageCut.setMinLat(latMin + "");
                imageCut.setMaxLon(lngMax + "");
                imageCut.setMaxLat(latMax + "");
                imageCutService.save(imageCut);
                log.info("切图成功");
                return cutId;
            }  finally {
                dataset.delete();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            redisUtil.del(redId + redisKey);
        }
        return status;
    }

    @Override
    public ImageCut imageCut(String redId, String tifFile, int type, String remark) {
        try {
            String cutId = snow.next() + "";
            String dbPath = fileDir + "/cutOut/" + cutId + ".idb";
            FileUtil.del(dbPath);
            String wgs84 = isWGS84(tifFile);
            if (!FileElseUtil.isDouble(wgs84)) {
                tifFile = wgs84;
            } else {
                return null;
            }
            log.info("切图影像地址为:{}", tifFile);
            DBUtils.copyFileByTemplate(DBUtils.TILE_TEMPLATE, dbPath);
            GridCoverage2D gridCoverage = GetGridCoverage2D(fileDir + tifFile);
            if (null == gridCoverage) {
                return null;
            }
            boolean isTransform = false;
            CoordinateReferenceSystem crs = gridCoverage.getCoordinateReferenceSystem();
            if (crs instanceof DefaultProjectedCRS) {
                isTransform = true;
            } else if (!(crs instanceof DefaultGeographicCRS)) {
                return null;
            }
            String code = null;
            try {
                code = CRS.lookupIdentifier(crs, true);
            } catch (FactoryException e) {
                return null;
            }
            System.out.println("EPSG code:" + code);
            if (isTransform && StringUtils.isBlank(code)) {
                return null;
            }
            Dataset dataset = gdal.Open(fileDir + tifFile, gdalconstConstants.GA_ReadOnly);
            if (ObjectUtils.isEmpty(dataset)) {
                log.error(gdal.GetLastErrorNo() + "===" + gdal.GetLastErrorMsg());
                return null;
            }
            try {
                double[] geoTransform = dataset.GetGeoTransform();
                double[] defaultGetGeoTransform = {0, 1, 0, 0, 0, 1};
                if (Arrays.equals(geoTransform, defaultGetGeoTransform)) {
                    return null;
                }
                int xSize = dataset.getRasterXSize();
                int ySize = dataset.getRasterYSize();
                double lngMin = geoTransform[0];
                double angleX = geoTransform[2];
                double latMax = geoTransform[3];
                double lngMax = lngMin + (xSize * geoTransform[1]) + (ySize * angleX);
                double latMin = latMax + (xSize * geoTransform[4]) + (ySize * geoTransform[5]);
                if (isTransform && StringUtils.isNotBlank(code)) {
                    CoordinateReferenceSystem sourceCRS = CRS.decode(code);
                    CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326");
                    MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, false);
                    Coordinate lngLatMax = JTS.transform(new Coordinate(lngMax, latMax), null, transform);
                    Coordinate lngLatMin = JTS.transform(new Coordinate(lngMin, latMin), null, transform);
                    lngMax = lngLatMax.getY();
                    latMax = lngLatMax.getX();
                    lngMin = lngLatMin.getY();
                    latMin = lngLatMin.getX();
                }
                JSONArray position = MercatorWmtsUtils.getCutCenterByArr(lngMin, lngMax, latMin, latMax);
                double srcWePixelResolution = (lngMax - lngMin) / xSize;
                double srcNsPixelResolution = (latMax - latMin) / ySize;
                int zoom = 1;
                for (; zoom <= 20; zoom++) {
                    int[] tilePointMax = MercatorWmtsUtils.coordinates2tile(lngMax, latMax, zoom);
                    int[] tilePointMin = MercatorWmtsUtils.coordinates2tile(lngMin, latMin, zoom);
                    int tileRowMax = tilePointMin[1];
                    int tileColMax = tilePointMax[0];
                    int tileRowMin = tilePointMax[1];
                    int tileColMin = tilePointMin[0];
                    if (tileRowMax - tileRowMin + 1 < 4 || tileColMax - tileColMin + 1 < 4) {
                        continue;
                    }
                    double resolution = 180d / Math.pow(2, 7 + zoom);
                    if (resolution < srcWePixelResolution) {
                        break;
                    }
                    log.info("共有" + (tileRowMax - tileRowMin + 1) * (tileColMax - tileColMin + 1) + "张");
                    for (int row = tileRowMin; row <= tileRowMax; row++) {
                        for (int col = tileColMin; col <= tileColMax; col++) {
                            double tempLatMin = MercatorWmtsUtils.tile2lat(row + 1, zoom);
                            double tempLatMax = MercatorWmtsUtils.tile2lat(row, zoom);
                            double tempLonMin = MercatorWmtsUtils.tile2lng(col, zoom);
                            double tempLonMax = MercatorWmtsUtils.tile2lng(col + 1, zoom);
                            ReferencedEnvelope tileBound = new ReferencedEnvelope(tempLonMin, tempLonMax, tempLatMin, tempLatMax, DefaultGeographicCRS.WGS84);
                            ReferencedEnvelope imageBound = new ReferencedEnvelope(lngMin, lngMax, latMin, latMax, DefaultGeographicCRS.WGS84);
                            ReferencedEnvelope intersect = tileBound.intersection(imageBound);
                            double dstWePixelResolution = (tempLonMax - tempLonMin) / MercatorWmtsUtils.TILE_SIZE;
                            double dstNsPixelResolution = (tempLatMax - tempLatMin) / MercatorWmtsUtils.TILE_SIZE;
                            int offsetX = (int) ((intersect.getMinX() - lngMin) / srcWePixelResolution);
                            int offsetY = (int) Math.abs((intersect.getMaxY() - latMax) / srcNsPixelResolution);
                            int blockXSize = (int) ((intersect.getMaxX() - intersect.getMinX()) / srcWePixelResolution);
                            int blockYSize = (int) ((intersect.getMaxY() - intersect.getMinY()) / srcNsPixelResolution);
                            int imageXBuf = (int) Math.ceil((intersect.getMaxX() - intersect.getMinX()) / dstWePixelResolution);
                            int imageYBuf = (int) Math.ceil(Math.abs((intersect.getMaxY() - intersect.getMinY()) / dstNsPixelResolution));
                            int imageOffsetX = (int) ((intersect.getMinX() - tempLonMin) / dstWePixelResolution);
                            int imageOffsetY = (int) Math.abs((intersect.getMaxY() - tempLatMax) / dstNsPixelResolution);
                            imageOffsetX = imageOffsetX > 0 ? imageOffsetX : 0;
                            imageOffsetY = imageOffsetY > 0 ? imageOffsetY : 0;
                            Band inBand1 = dataset.GetRasterBand(1);
                            Band inBand2 = dataset.GetRasterBand(2);
                            Band inBand3 = dataset.GetRasterBand(3);
                            int[] band1BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            int[] band2BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            int[] band3BuffData = new int[MercatorWmtsUtils.TILE_SIZE * MercatorWmtsUtils.TILE_SIZE * gdalconst.GDT_Int32];
                            inBand1.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band1BuffData, 0, 0);
                            inBand2.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band2BuffData, 0, 0);
                            inBand3.ReadRaster(offsetX, offsetY, blockXSize, blockYSize, imageXBuf, imageYBuf, gdalconst.GDT_Int32, band3BuffData, 0, 0);
                            Driver memDriver = gdal.GetDriverByName("MEM");
                            Dataset msmDS = memDriver.Create("msmDS", 256, 256, 4);
                            Band dstBand1 = msmDS.GetRasterBand(1);
                            Band dstBand2 = msmDS.GetRasterBand(2);
                            Band dstBand3 = msmDS.GetRasterBand(3);
                            Band alphaBand = msmDS.GetRasterBand(4);
                            int[] alphaData = new int[256 * 256 * gdalconst.GDT_Int32];
                            for (int index = 0; index < alphaData.length; index++) {
                                if (band1BuffData[index] > 0) {
                                    alphaData[index] = 255;
                                }
                            }
                            dstBand1.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band1BuffData);
                            dstBand2.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band2BuffData);
                            dstBand3.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, band3BuffData);
                            alphaBand.WriteRaster(imageOffsetX, imageOffsetY, imageXBuf, imageYBuf, alphaData);

                            String pngPath = keyWord.getRootDir() + keyWord.getOutputDir() + File.separator + cutId + File.separator + zoom + "-" + col + "-" + row + ".png";
                            File file = new File(pngPath);
                            if (!file.getParentFile().exists()) {
                                file.getParentFile().mkdirs();
                            }

                            Driver pngDriver = gdal.GetDriverByName("PNG");
                            Dataset pngDs = pngDriver.CreateCopy(pngPath, msmDS);
                            msmDS.FlushCache();
                            msmDS.delete();
                            try (InputStream fis = new FileInputStream(pngPath)) {
                                byte[] imgBytes = IOUtils.toByteArray(fis);
                                String quadKey = MercatorWmtsUtils.xyzToQuadKey(col, row, zoom);
                                DBUtils.save(dbPath, imgBytes, quadKey);
                            } catch (IOException e) {
                                log.error("切图异常" + e.getMessage(), e);
                            }
                            pngDs.delete();
                        }
                    }
                }
                ImageCut imageCut = new ImageCut();
                imageCut.setId(cutId);
                imageCut.setRedId(redId);
                imageCut.setImageType(type + "");
                imageCut.setImageUrl(tifFile);
                imageCut.setPosition(position.toJSONString());
                imageCut.setLon(position.getString(0));
                imageCut.setLat(position.getString(1));
                FileUtil.mkdir(fileDir + "/image/thumb");
                CommonUtil.getImage(fileDir + tifFile, fileDir + "/image/thumb/" + cutId + ".jpg");
                imageCut.setImage("/image/thumb/" + cutId + ".jpg");
                CommonUtil.generateThumbnail(fileDir + tifFile, fileDir + "/image/thumb/" + cutId + "_thumb.jpg", 200, 200);
                imageCut.setThumb("/image/thumb/" + cutId + "_thumb.jpg");
                imageCut.setRemark(remark);
                imageCut.setMinLon(lngMin + "");
                imageCut.setMinLat(latMin + "");
                imageCut.setMaxLon(lngMax + "");
                imageCut.setMaxLat(latMax + "");
                imageCutService.save(imageCut);
                log.info("切图成功");
                return imageCut;
            }  finally {
                dataset.delete();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private int get256(int i) {
        int n = 256;
        while (n < i) {
            n *= 2;
        }
        return n;
    }

    private int getBig(int i1, int i2) {
        return i1 > i2 ? i1 : i2;
    }

    private GridCoverage2D GetGridCoverage2D(String geoTifPath) {
        File geoTifFile = new File(geoTifPath);
        if (!geoTifFile.exists()) {
            log.error("geoTif文件不存在");
            return null;
        }
        AbstractGridFormat format = GridFormatFinder.findFormat(geoTifFile);

        if (!(format instanceof GeoTiffFormat)) {
            log.error(String.format("传入文件\"%s\"不是geoTif格式文件", geoTifPath));
            return null;
        }
        Hints hints = new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);

        AbstractGridCoverage2DReader geoTifReader = format.getReader(geoTifFile, hints);
        try {
            if (ObjectUtils.isEmpty(geoTifReader)) {
                return null;
            }
            return geoTifReader.read(null);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    private static GridCoverage2D get2D(String geoTifPath) {
        File geoTifFile = new File(geoTifPath);
        if (!geoTifFile.exists()) {
            throw new RuntimeException("geoTif文件不存在");
        }
        AbstractGridFormat format = GridFormatFinder.findFormat(geoTifFile);

        if (!(format instanceof GeoTiffFormat)) {
            throw new RuntimeException(String.format("传入文件\"%s\"不是geoTif格式文件", geoTifPath));
        }
        Hints hints = new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);

        AbstractGridCoverage2DReader geoTifReader = format.getReader(geoTifFile, hints);
        try {
            if (ObjectUtils.isEmpty(geoTifReader)) {
                return null;
            }
            return geoTifReader.read(null);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

}
